package org.dromara.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.websocket.dto.WebSocketMessageDto;
import org.dromara.common.websocket.utils.WebSocketUtils;
import org.dromara.system.domain.TrtcPinStatus;
import org.dromara.system.domain.vo.TrtcPinStatusVo;
import org.dromara.system.mapper.TrtcPinStatusMapper;
import org.dromara.system.service.ITrtcPinStatusService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * TRTC用户置顶状态Service实现
 *
 * @author Lion Li
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class TrtcPinStatusServiceImpl extends ServiceImpl<TrtcPinStatusMapper, TrtcPinStatus> implements ITrtcPinStatusService {

    private static final String CACHE_KEY_PREFIX = "trtc:pin:";
    private static final long CACHE_EXPIRE_TIME = 24; // 缓存过期时间（小时）

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean setPinStatus(String roomId, String userId, boolean isPinned) {
        if (StringUtils.isAnyBlank(roomId, userId)) {
            throw new IllegalArgumentException("房间ID和用户ID不能为空");
        }

        // 更新数据库
        TrtcPinStatus pinStatus = new TrtcPinStatus();
        pinStatus.setRoomId(roomId);
        pinStatus.setUserId(userId);
        pinStatus.setIsPinned(isPinned);
        pinStatus.setPinTime(LocalDateTime.now());

        boolean success = saveOrUpdate(pinStatus);
        if (success) {
            // 更新缓存
//            String cacheKey = getCacheKey(roomId);
//            RedisUtils.deleteObject(cacheKey);

            // 发送WebSocket通知
            sendPinStatusNotification(roomId, userId, isPinned);
        }

        return success;
    }

    @Override
    public List<TrtcPinStatusVo> getPinStatusList(String roomId) {
        if (StringUtils.isBlank(roomId)) {
            throw new IllegalArgumentException("房间ID不能为空");
        }

        // 尝试从缓存获取
//        String cacheKey = getCacheKey(roomId);
//        Map<String, Object> cachedResult = RedisUtils.getCacheMap(cacheKey);
//        if (cachedResult != null && !cachedResult.isEmpty()) {
//            return cachedResult;
//        }

        // 从数据库查询
        List<TrtcPinStatus> pinStatusList = list(new LambdaQueryWrapper<TrtcPinStatus>()
            .eq(TrtcPinStatus::getRoomId, roomId)
            .eq(TrtcPinStatus::getIsPinned, true)
            .orderByDesc(TrtcPinStatus::getPinTime));

        // 转换为Map，包含置顶状态和时间信息
//        Map<String, Object> result = new LinkedHashMap<>();
//        // 按照pinTime降序排序后的列表
//        List<TrtcPinStatus> sortedList = pinStatusList.stream()
//            .sorted(Comparator.comparing(TrtcPinStatus::getPinTime).reversed())
//            .collect(Collectors.toList());
//
//        for (TrtcPinStatus status : sortedList) {
//            Map<String, Object> userStatus = new HashMap<>();
//            userStatus.put("isPinned", status.getIsPinned());
//            userStatus.put("pinTime", status.getPinTime());
//            result.put(status.getUserId(), userStatus);
//        }

        // 转换为 DTO 列表
        List<TrtcPinStatusVo> result = new ArrayList<>();
        for (TrtcPinStatus status : pinStatusList) {
            TrtcPinStatusVo trtcPinStatusVo = new TrtcPinStatusVo();
            trtcPinStatusVo.setUserId(status.getUserId());
            trtcPinStatusVo.setIsPinned(status.getIsPinned());
            trtcPinStatusVo.setPinTime(status.getPinTime());
            result.add(trtcPinStatusVo);
        }

        // 打印result信息
        log.info("Pin status result for room {}: ", roomId);
        for (TrtcPinStatusVo dto : result) {
            log.info("User: {}, isPinned: {}, pinTime: {}",
                dto.getUserId(), dto.getIsPinned(), dto.getPinTime());
        }

        // 更新缓存
//        RedisUtils.setCacheMap(cacheKey, result);
//        RedisUtils.expire(cacheKey, Duration.ofHours(CACHE_EXPIRE_TIME));

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelPinStatus(String roomId, String userId) {
        if (StringUtils.isAnyBlank(roomId, userId)) {
            throw new IllegalArgumentException("房间ID和用户ID不能为空");
        }

        // 更新数据库
        boolean success = remove(new LambdaQueryWrapper<TrtcPinStatus>()
            .eq(TrtcPinStatus::getRoomId, roomId)
            .eq(TrtcPinStatus::getUserId, userId));

        if (success) {
            // 更新缓存
//            String cacheKey = getCacheKey(roomId);
//            RedisUtils.deleteObject(cacheKey);

            // 发送WebSocket通知
            sendPinStatusNotification(roomId, userId, false);
        }

        return success;
    }

    /**
     * 获取缓存key
     */
    private String getCacheKey(String roomId) {
        return CACHE_KEY_PREFIX + roomId;
    }

    /**
     * 发送WebSocket通知
     */
    private void sendPinStatusNotification(String roomId, String userId, boolean isPinned) {
        // 构建通知消息
        Map<String, Object> message = new HashMap<>();
        message.put("type", "pin_status");
        message.put("roomId", roomId);
        message.put("userId", userId);
        message.put("isPinned", isPinned);
        message.put("pinTime", LocalDateTime.now());

        // 创建WebSocket消息DTO
        WebSocketMessageDto webSocketMessageDto = new WebSocketMessageDto();
        webSocketMessageDto.setMessage(JsonUtils.toJsonString(message));

        // 发送到房间内所有用户
        WebSocketUtils.publishAll(webSocketMessageDto.getMessage());
    }
}
